package cn.trigram.file;

import cn.trigram.logging.Log;
import cn.trigram.logging.LogFactory;
import java.io.ByteArrayOutputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;

/**
 * 文件分分割处理器，以多线程的方式实现
 */
public class FileSegmentHandler implements Runnable {

  final Log log = LogFactory.getLog(FileSegmentHandler.class);

  /**
   * 源文件的路径
   */
  private String sourceFilePath;

  /**
   * 当前段起始位置
   */
  private long start;

  /**
   * 当前段结束位置
   */
  private long end;

  private Charset charset;

  public FileSegmentHandler(String sourceFilePath, long startPosition, long endPosition,
      Charset charset) {

    this.sourceFilePath = sourceFilePath;
    this.start = startPosition;
    this.end = endPosition;
    this.charset = charset;
  }

  @Override
  public void run() {
//      开始分割文件
    try (
        RandomAccessFile randomAccessFile = new RandomAccessFile(sourceFilePath, "r");
        FileChannel channel = randomAccessFile.getChannel();
        ByteArrayOutputStream bos = new ByteArrayOutputStream()
    ) {
      ByteBuffer channelBuffer = ByteBuffer.allocate(1024);
      byte[] channelBufferDest = new byte[1024];
//        调整到当前段的起始位置
      channel.position(this.start);
      while (true) {
        channelBuffer.clear();
        long readPositionBefore = channel.position();
        int readByteNum = channel.read(channelBuffer);
        if (readByteNum == -1) {
//            读取结束
          break;
        }
        long readPositionAfter = channel.position();
        channelBuffer.flip();
        channelBuffer.get(channelBufferDest, 0, readByteNum);
        if (readPositionAfter > this.end) {
//            超过当前段的结束位置需要调整本次读取的字节数
          readByteNum = new Long(this.end - readPositionBefore).intValue();
        }
        bos.write(channelBufferDest, 0, new Long(readByteNum).intValue());
        if (readPositionAfter > this.end) {
//            超过当前段的结束位置表示分割结束，同时调整channel的位置，为下一段的起始位置
          channel.position(this.end);
          break;
        }
      }
//      todo 简单的演示输出为字符串
      System.out.println(bos.toString(charset.name()));
    } catch (Exception e) {
      log.error(String
          .format("分割文件【%s】的第【%d-%d】位置分割失败；【%s】", this.sourceFilePath, this.start, this.end,
              e.getLocalizedMessage()));
    }
  }

}
